home *** CD-ROM | disk | FTP | other *** search
- /* Implements a scroll bar. The scroll bar may optionally have an actual
- control associated with it; if no control is present, you can still use
- the scroll bar structure to set and get the minimum and maximum value
- of the control. The application must provide functions to be called
- when the user clicks in the scroll bar. The scroll bar's value may
- range from 0..LONG_MAX. The value is scaled for the scroll bar
- control to fit in the range 0..SHRT_MAX.
-
- 94/01/12 aih - added brief comment
- 93/12/15 aih - vals are longs, and are scaled to short for ctl if >SHRT_MAX
- 93/12/05? aih - added frame library for borders
- 93/11/?? aih - added min width and height and resize functions
- 93/03/30 aih - created */
-
- #include "ControlLib.h"
- #include "DrawLib.h"
- #include "EventLib.h"
- #include "GlobalLib.h"
- #include "MathLib.h"
- #include "MemoryLib.h"
- #include "RectangleLib.h"
- #include "ScrollBarLib.h"
- #include "WindowLib.h"
-
- /* return minimum width for a view with scroll bars */
- short SBarMinWidth(Boolean horizontal, Boolean vertical)
- {
- return((horizontal ? SBAR_MIN_LENGTH : 0) + (vertical ? SBAR_WIDTH : 0));
- }
-
- /* return minimum height for a view with scroll bars */
- short SBarMinHeight(Boolean horizontal, Boolean vertical)
- {
- return((vertical ? SBAR_MIN_LENGTH : 0) + (horizontal ? SBAR_WIDTH : 0));
- }
-
- /* true if a valid scroll bar */
- Boolean SBarValid(ScrollBarHandle sbar)
- {
- if (! HandleValidSize(sbar, sizeof(ScrollBarType))) return(false);
- if ((**sbar).ctl && ! CtlValid((**sbar).ctl)) return(false);
- return(true);
- }
-
- /* allocate a new scroll bar */
- ScrollBarHandle SBarBegin(WindowPtr window, const Rect *bounds,
- FrameHandle frame)
- {
- volatile ScrollBarHandle sbar = NULL;
- ControlHandle ctl = NULL;
-
- require(WinValid(window));
- require(! bounds || RectValid(bounds));
- require(! frame || FrameValid(frame));
- TRY {
- sbar = HandleBeginClear(sizeof(ScrollBarType));
- (**sbar).window = window;
- (**sbar).frame = frame;
- if (bounds) {
- ctl = NewControl(window, bounds, (StringPtr) "\p",
- false, 0, 0, 0, scrollBarProc, 0L);
- (**sbar).ctl = ctl;
- FailNIL(ctl);
- SetCRefCon(ctl, (long) sbar);
- }
- if (frame && ctl) {
- if (SBarIsHorizontal(sbar)) {
- FrameFlagsSet(frame, FrameFlags(frame) | FRAME_HSCROLL);
- (**frame).bounds.bottom += SBAR_WIDTH - 1;/* program_note: not best place to set this */
- }
- else {
- FrameFlagsSet(frame, FrameFlags(frame) | FRAME_VSCROLL);
- (**frame).bounds.right += SBAR_WIDTH - 1;/* program_note: not best place to set this */
- }
- }
- WinRegister(window, sbar, SBarEventTable());
- ensure(SBarValid(sbar));
- } CATCH {
- SBarEnd(sbar);
- } ENDTRY;
- return(sbar);
- }
-
- /* dispose of the scroll bar */
- void SBarEnd(ScrollBarHandle sbar)
- {
- if (sbar) {
- WinUnregister((**sbar).window, sbar);
- if ((**sbar).ctl) DisposeControl((**sbar).ctl);
- HandleEnd(sbar);
- sbar = NULL;
- }
- ensure(! SBarValid(sbar));
- }
-
- /* return handle to scroll bar's control */
- ControlHandle SBarCtl(ScrollBarHandle sbar)
- {
- require(SBarValid(sbar));
- return((**sbar).ctl);
- }
-
- /* return current value of scroll bar */
- long SBarVal(ScrollBarHandle sbar)
- {
- require(SBarValid(sbar));
- return((**sbar).val);
- }
-
- /* set current value of scroll bar */
- void SBarValSet(ScrollBarHandle sbar, long val)
- {
- require(SBarValid(sbar));
- require(0 <= val && val <= (**sbar).maxval);
- (**sbar).val = val;
- if ((**sbar).ctl) {
- if ((**sbar).maxval > SHRT_MAX)
- val = (float) (**sbar).val / (**sbar).maxval * SHRT_MAX;
- check(0 <= val && val <= SHRT_MAX);
- SetCtlValue((**sbar).ctl, val);
- }
- ensure(SBarValid(sbar));
- }
-
- /* return maximum value of scroll bar */
- long SBarMax(ScrollBarHandle sbar)
- {
- require(SBarValid(sbar));
- return((**sbar).maxval);
- }
-
- /* set maximum value of scroll bar */
- void SBarMaxSet(ScrollBarHandle sbar, long maxval)
- {
- require(SBarValid(sbar));
- require(maxval >= 0);
- (**sbar).maxval = maxval;
- if ((**sbar).ctl)
- SetCtlMax((**sbar).ctl, min((**sbar).maxval, SHRT_MAX));
- ensure(SBarValid(sbar));
- }
-
- /* set data passed to call-back functions */
- void SBarDataSet(ScrollBarHandle sbar, void *data)
- {
- require(SBarValid(sbar));
- (**sbar).data = data;
- ensure(SBarValid(sbar));
- }
-
- /* set function called when there's a click in the control */
- void SBarActionSet(ScrollBarHandle sbar, void (*action)(void *data, short part))
- {
- require(SBarValid(sbar));
- (**sbar).action = action;
- ensure(SBarValid(sbar));
- }
-
- /* set function called when there's a click in the thumb area */
- void SBarThumbSet(ScrollBarHandle sbar, void (*thumb)(void *data, long delta))
- {
- require(SBarValid(sbar));
- (**sbar).thumb = thumb;
- ensure(SBarValid(sbar));
- }
-
- /* true if a horizontal scroll bar */
- Boolean SBarIsHorizontal(ScrollBarHandle sbar)
- {
- Rect bounds;
- Boolean result = false;
-
- if ((**sbar).ctl) {
- CtlRect((**sbar).ctl, &bounds);
- result = (RectWidth(&bounds) >= RectHeight(&bounds));
- }
- return(result);
- }
-
- /* true if a vertical scroll bar */
- Boolean SBarIsVertical(ScrollBarHandle sbar)
- {
- return((**sbar).ctl && ! SBarIsHorizontal(sbar));
- }
-
- /* resize the scroll bar */
- void SBarResize(ScrollBarHandle sbar, short dh, short dv)
- {
- Rect bounds;
- GrafPtr port = NULL;
- Rect empty = { 0, 0, 0, 0 };
- RgnHandle clip;
-
- require(SBarValid(sbar));
- if ((**sbar).frame) {
- if ((FrameFlags((**sbar).frame) & FRAME_ANCHOR_RIGHT) == 0) dh = 0;
- if ((FrameFlags((**sbar).frame) & FRAME_ANCHOR_BOTTOM) == 0) dv = 0;
- }
- if ((**sbar).ctl && (dh || dv)) {
- GetPort(&port);
- SetPort(CtlWindow((**sbar).ctl));
- CtlRect((**sbar).ctl, &bounds);
- EraseRect(&bounds);
- InvalRect(&bounds);
- clip = BeginRgn();
- GetClip(clip);
- ClipRect(&empty);
- if (SBarIsVertical(sbar)) {
- check(RectHeight(&bounds) + dv >= SBAR_MIN_LENGTH);
- if (dh) MoveControl((**sbar).ctl, bounds.left + dh, bounds.top);
- if (dv) SizeControl((**sbar).ctl, RectWidth(&bounds), RectHeight(&bounds) + dv);
- }
- else {
- check(SBarIsHorizontal(sbar));
- check(RectWidth(&bounds) + dh >= SBAR_MIN_LENGTH);
- if (dv) MoveControl((**sbar).ctl, bounds.left, bounds.top + dv);
- if (dh) SizeControl((**sbar).ctl, RectWidth(&bounds) + dh, RectHeight(&bounds));
- }
- CtlRect((**sbar).ctl, &bounds);
- InvalRect(&bounds);
- SetClip(clip);
- SetPort(port);
- EndRgn(clip);
- }
- }
-
- /* activate or deactivate the scroll bar */
- void SBarActivate(ScrollBarHandle sbar, Boolean activate)
- {
- Rect bounds;
- GrafPtr port = NULL;
-
- require(SBarValid(sbar));
- if ((**sbar).ctl) {
- GetPort(&port);
- SetPort((**sbar).window);
- CtlRect((**sbar).ctl, &bounds);
- if (activate) {
- if (CtlVisible((**sbar).ctl))
- Draw1Control((**sbar).ctl);
- else
- ShowControl((**sbar).ctl);
- }
- else {
- if (CtlVisible((**sbar).ctl))
- HideControl((**sbar).ctl);
- FrameRect(&bounds);
- InsetRect(&bounds, 1, 1);
- EraseRect(&bounds);
- }
- ValidRect(&bounds);
- SetPort(port);
- }
- ensure(SBarValid(sbar));
- }
-
- /* redraw the scroll bar */
- void SBarUpdate(ScrollBarHandle sbar)
- {
- Rect bounds;
- GrafPtr port = NULL;
-
- require(SBarValid(sbar));
- if ((**sbar).ctl) {
- if (CtlVisible((**sbar).ctl))
- /* Draw1Control((**sbar).ctl) */; /* update done by UpdtControl */
- else {
- GetPort(&port);
- SetPort((**sbar).window);
- CtlRect((**sbar).ctl, &bounds);
- FrameRect(&bounds);
- InsetRect(&bounds, 1, 1);
- EraseRect(&bounds);
- SetPort(port);
- }
- }
- ensure(SBarValid(sbar));
- }
-
- /* true if the point is within the scroll bar */
- Boolean SBarWithin(ScrollBarHandle sbar, Point where)
- {
- require(SBarValid(sbar));
- return((**sbar).ctl && TestControl((**sbar).ctl, where) != 0);
- }
-
- /* the function passed to TrackControl for clicks not in the thumb */
- static pascal void ScrollProc(ControlHandle ctl, short part)
- {
- ScrollBarHandle sbar = NULL;
-
- require(CtlValid(ctl));
- if (part) {
- sbar = (ScrollBarHandle) GetCRefCon(ctl);
- check(SBarValid(sbar));
- (**sbar).action((**sbar).data, part);
- }
- }
-
- /* handle a click in the scroll bar */
- void SBarClick(ScrollBarHandle sbar, Point where)
- {
- long delta;
- short val;
-
- require(SBarValid(sbar));
- if ((**sbar).ctl) {
- switch (TestControl((**sbar).ctl, where)) {
- case inUpButton:
- case inDownButton:
- case inPageUp:
- case inPageDown:
- TrackControl((**sbar).ctl, where, (ProcPtr) ScrollProc);
- break;
- case inThumb:
- val = GetCtlValue((**sbar).ctl);
- TrackControl((**sbar).ctl, where, (ProcPtr) NULL);
- delta = val - GetCtlValue((**sbar).ctl);
- if ((**sbar).maxval > SHRT_MAX)
- delta *= (float) (**sbar).maxval / SHRT_MAX;
- (**sbar).thumb((**sbar).data, delta);
- break;
- }
- }
- ensure(SBarValid(sbar));
- }
-
- /* handle a mouse down event in the scroll bar */
- void SBarMouseDown(ScrollBarHandle sbar, EventRecord *event)
- {
- Point where = event->where;
-
- require(SBarValid(sbar));
- GlobalToPort(&where, (**sbar).window);
- SBarClick(sbar, where);
- ensure(SBarValid(sbar));
- }
-